<script>
export default {
  name: 'DTree',
  props: {
    multiple: {
      type: Boolean,
      default: false
    },
    loadData: {
      type: Function
    },
    treeData: {
      type: Array,
      default: () => []
    },
    replaceFields: {
      type: Object,
      default: () => ({
        children: 'children',
        title: 'title',
        key: 'key'
      })
    },
    expandedKeys: {
      type: Array
    },
    selectedKeys: {
      type: Array,
      default: () => []
    },
    loadedKeys: {
      type: Array,
      default: () => []
    },
    showIcon: {
      type: Boolean,
      default: false
    },
    draggable: {
      type: Boolean,
      default: false
    },
    itemKey: {
      type: String,
      default: 'key'
    },
    checkDragInto: {
      type: Function
    },
    defaultExpandAll: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    onExpand(expandedKeys) {
      this.$emit('expand', expandedKeys);
    },
    onLoad(loadedKeys) {
      this.$emit('load', loadedKeys);
    },
    onSelect(keys, e) {
      this.$emit('select', keys, e);
    },
    onDrop(info) {
      const dropKey = info.node.eventKey;
      const dragKey = info.dragNode.eventKey;
      const dropPos = info.node.pos.split('-');
      const dropPosition =
        info.dropPosition - Number(dropPos[dropPos.length - 1]);
      const loop = (data, key, callback) => {
        data.forEach((item, index, arr) => {
          if (item[this.itemKey] === key) {
            return callback(item, index, arr);
          }
          if (item.children) {
            return loop(item.children, key, callback);
          }
        });
      };
      const data = [...this.treeData];

      // Find dragObject
      let dragObj;
      loop(data, dragKey, item => {
        dragObj = item;
      });
      if (!info.dropToGap) {
        // Find dropObject
        let dropObj;
        loop(data, dropKey, item => {
          dropObj = item;
        });
        if (!this.checkDragInto || this.checkDragInto(dragObj, dropObj)) {
          // into
          this.$emit('dropInto', {
            dragObj,
            dropObj
          });
          // Delete drag
          loop(data, dragKey, (item, index, arr) => {
            arr.splice(index, 1);
          });
          // Drop on the content
          dropObj.children = dropObj.children || [];
          dropObj.children.push(dragObj);
        }
      } else {
        let ar;
        let i;
        // Find dropObject
        let dropObj;
        loop(data, dropKey, (item, index, arr) => {
          ar = arr;
          i = index;
          dropObj = item;
        });
        // Delete drag
        loop(data, dragKey, (item, index, arr) => {
          arr.splice(index, 1);
        });
        if (dropPosition === -1) {
          // down line
          this.$emit('dropOutOrSort', {
            dragObj,
            dropObj
          });
          ar.splice(i, 0, dragObj);
        } else {
          // up line
          this.$emit('dropOutOrSort', {
            dragObj,
            dropObj
          });
          ar.splice(i + 1, 0, dragObj);
        }
      }
      this.$emit('drop', data);
    }
  },
  render() {
    const props = {
      loadData: this.loadData,
      treeData: this.treeData,
      replaceFields: this.replaceFields,
      selectedKeys: this.selectedKeys,
      loadedKeys: this.loadedKeys,
      showIcon: this.showIcon,
      draggable: this.draggable,
      defaultExpandAll: this.defaultExpandAll
    };
    if (this.expandedKeys) {
      props.expandedKeys = this.expandedKeys;
    }
    const on = {
      expand: this.onExpand,
      load: this.onLoad,
      drop: this.onDrop,
      select: this.onSelect
    };
    return (
      <a-tree
        props={props}
        multiple={this.multiple}
        scopedSlots={this.$scopedSlots}
        on={on}
        class="tree-container"
      >
        <slot />
      </a-tree>
    );
  }
};
</script>

<style lang="scss" scoped>
.tree-container {
  ::v-deep li {
    position: relative;
    padding: 0;
  }
  ::v-deep .tw-tree-switcher {
    position: absolute;
  }
  ::v-deep .tw-tree-node-content-wrapper {
    width: 100%;
    padding-left: 24px;
    .tw-tree-icon__customize i {
      font-size: 13px;
    }
    .tw-tree-title {
      display: inline-block;
      width: calc(100% - 24px);
    }
  }
  // 第2级（因设计要求，需要样式适配到整行，根据层级写死样式）
  ::v-deep .tw-tree-child-tree {
    padding: 0;
    .tw-tree-switcher {
      padding-left: 22px;
    }
    .tw-tree-node-content-wrapper {
      padding-left: 46px;
    }
    // 第3级
    .tw-tree-child-tree {
      padding: 0;
      .tw-tree-switcher {
        padding-left: 44px;
      }
      .tw-tree-node-content-wrapper {
        padding-left: 68px;
      }
      // 第4级
      .tw-tree-child-tree {
        padding: 0;
        .tw-tree-switcher {
          padding-left: 66px;
        }
        .tw-tree-node-content-wrapper {
          padding-left: 90px;
        }
        // 第5级
        .tw-tree-child-tree {
          padding: 0;
          .tw-tree-switcher {
            padding-left: 88px;
          }
          .tw-tree-node-content-wrapper {
            padding-left: 112px;
          }
          // 第6级
          .tw-tree-child-tree {
            padding: 0;
            .tw-tree-switcher {
              padding-left: 110px;
            }
            .tw-tree-node-content-wrapper {
              padding-left: 132px;
            }
            // 第7级
            .tw-tree-child-tree {
              padding: 0;
              .tw-tree-switcher {
                padding-left: 132px;
              }
              .tw-tree-node-content-wrapper {
                padding-left: 154px;
              }
              // 第8级
              .tw-tree-child-tree {
                padding: 0;
                .tw-tree-switcher {
                  padding-left: 154px;
                }
                .tw-tree-node-content-wrapper {
                  padding-left: 176px;
                }
              }
            }
          }
        }
      }
    }
  }
}
</style>
